perm filename F8OLD[3,ALS] blob
sn#289769 filedate 1977-06-26 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00015 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 Checkers on an F8
C00007 00003 Approximate ROM space requirements (ball park guesses at best)
C00008 00004 RAM Data space requirements in bytes for a look-aread of 10
C00015 00005 TENTATIVE DATA STORAGE MAP
C00019 00006 *CTAB EMPTY and LEGAL codes
C00029 00007 Subroutine to move 4 bytes from RAM to Scratchpad registers 16 thru 19
C00031 00008 * Registers, Subroutines
C00038 00009 * FORE AFT FIND
C00043 00010 *SELECT is entered with H set for the correct ply position in RAM
C00049 00011 UPDATE
C00050 00012 Evaluation
C00051 00013 α-β Scoring
C00052 00014 Opponents move checking
C00053 00015 DISPLAY
C00054 ENDMK
C⊗;
Checkers on an F8
The following is a first cut at trying to formulate the problem of writing
a simplified checker playing program to run on the F8. The general idea
is to limit the storage space requirements at the expense of running time.
One would hope to produce a program that could challenge an amateur but
that would not necessarily interest a checker master. It should also be
possible for the user to select several levels of play.
General procedure
Play consists of investigating the consequences of all legal moves by
carrying out a tree search of all posible replies and counter replies to a
depth (defined as the ply) of perhaps 4. Because of jump moves it will be
necessary to go to much further along the tree on occasion and a maximum
depth of perhaps 10 seems to be indicated. The quality of play could be
fixed at one of several levels under operator control by changes to the
permited ply levels. Only a rudimentary evaluation would be done at the
ends of the tree but once the rest of the program was written then any
remaining code space could be used to elaborate on this function.
The procedure will be roughly as follows:
A Set up initial board position
B Display board position
Ask opponent to chose side
If opponent choses White, randomly select a stored first move
(One might also have some stored first replies)
D Display board and wait for opponents move
Check opponents move for legallity
Display board if move is legal and go to 1
Report non-acceptance and go to D
General tree search to a minimum depth of 4 and a maximum depth of 10
2: Select next legal move
If no moves available go to 5
3: Make move and find the resulting board
Add 1 to ply counter
1: Find all legal moves
If ply <4 go to 2
Evaluate current board position in terms of 5 parameters
If opponent's move go to 2
If jump move go to 2
4: Select only move that leads to a non-jump reply
If move available go to 3
If no moves lead to a non-jump reply then if ply≤10 go to 2
Evaluate terminal position
5: Make α-β comparison of score with previous level and back score
If ply=0 go to 6
Back up a level and subtract 1 from ply counter
If ply <4 go to 2
If jump move go to 2
If opponents move go to 2
Go to 4
6: If score is a win or lose,announce results and go to A
Report best machine move and go to D
Approximate ROM space requirements (ball park guesses at best)
Routine Normal Minimum
Legal 200 100
Select 50 20
Update 200 100
Evaluate 200 100
α-β score 50 50
Back up 50 30
Check move 50 30
Display 400 200
Report win-lose 50 20
Totals 1250 650
RAM Data space requirements in bytes for a look-aread of 10
Note: Most of this space can be freed to report the final move,
to updating the display and to check the opponents move.
Function Normal Minimum
Board 10@12 120 10@12 120
Moves 10@16 160 10@1 10
Flags 10@2 20 10@2 20
Score 10@2 20 10@1 10
Totals 320 160
It would be desirable to keep some of these data in the scratchpad
registers. It seems reasonable to try to keep one board position, enough
bytes to specify one or more possible moves and one resulting board
position. During look-ahead (that is while moving forward along the
tree), one would transfer the old initial board position and any unused
move information to RAM storage, move the just found board to the
initial-board position and generate and store new move information, to
again repeat the process. This would require at least 16 of the
scratchpad registers.
Actually at evaluation time it would be nice to be able to keep two
complete levels (with all move information retained) in scratchpad memory.
This would completely fill the scratchpad memory and leave no space for
intermediate results, so some compromise will have to be worked out.
Scratchpad space will always be in short supply.
General philosophy of storing boards and moves
Since there are numerous Bytes required to specify the data needed to
determine legal moves, to select one of these for investigation and to
produce the next board along the tree, it seems reasonable to group these
data togather and to go from one level in the tree to the next by
incrementing a saved value for the data counter by the number of bytes
used for each level. Operations at any specific ply would then be done by
smaller fixed increments of the data counter in a sequence that would be
the same for all plies.
A board position would be stored as 3 sets of 4 bytes each, one set for
the white pieces (including kings), one set for the Black pieces
(including Kings), and 1 set for all Kings. White Kings would then be
gotten when needed by ANDing the bytes for the White pieces with the bytes
for the Kings. The 32 bits in the sets of 4 bytes would refer to the
individual squares on the board and a piece on a given square would be
shown by a 1 in the corresponding bit position. This method of
representation is actually wastefull of space in that each set of 4 bytes
will usually have fewer than 12 bits on but the packing and unpacking
requirements for any known more-compact representation would be
horrendous.
Two scores, the α value and the β value must be saved with each board.
While it would be possible to limit each score to 4 bits, it seems
advisable to allow 8 bits for each so 2 bytes are so needed at each ply.
Saving moves
All available legal moves from a given board position can be stored in 4
sets of 4 bytes each. Each set would correspond to a given direction on
the board, one for right forward moves, one for left forward moves, one
for left backward moves, and one for right backward moves, the bit
positions occupied showing the piece position which can make the move. As
moves are explored, the bits showing these moves are errased and when all
16 bytes are empty the program backs up a level and tries for moves less
far down the move tree. Several flag bits are required, one bit to tell
if the moves are jump moves or not, one bit to tell which color is moving,
another bit to keep track of the ply level, still another to tell if the
next lower move was a jump, etc. One might be able to get by with one
byte of such flags but it would be safer and certainly easier if at least
two bytes were used.
The straight forward procedure would be to compute and store all available
moves with each board. Initially all directions must be investigated to
make sure that there are no jumps, since jumps must be taken. Thereafter
one could save space by keeping only one byte full of moves, with some
bookkeeping being required, and then by recomputing each additional byte
full as needed. This would save as many as 14 bytes per ply.
An alternate proceedure would be to keep only the count of the moves that
have been processed from each board position and to recompute all moves
over again each time and then count down to find what the next one would
be but little if any space would be saved by this procedure.
TENTATIVE DATA STORAGE MAP
As a first pass we will assign the following relative locations for tree data
Contents Location
Active pieces 0 thru 3
Passive pieces 4 thru 7
Kings 8 thru B
Move byte C
Flag byte D
Score bytes E and F
We will store tree data in the RAM such that the starting address is
divisable by 256, that is, so that the second byte of this address is
zero. The first byte of the data counter will be set at the start of the
tree analysis and will remain unchanged during the analysis. It may, of
course, be necessary to store the data counter ocassionaly during
excursions to subroutines, but the F8 code allows this to be done fairly
easily. We will reserve H (scratchpad registers 10 and 11) for storing
the value of the data counter when it is set to point to the start of a
data block as outlined below.
The tree data will consist of blocks of 16 bytes, one block for the
initial board situation at the start of any one move and the additional
blocks, one for each ply in depth to which the analysis is to be carried.
Normally this depth will be a fairly small number but provision will have
to be made for perhaps 16 blocks. It does not seem that RAM space will be
at all critical during the tree analysis and most of this space is used
only during the tree analysis itself and so it can be reused by other
parts of the overall program. A FREE STORAGE scheme will definitely not
have to be used by this part of the program.
Several scratchpad registers will be reserved for pertinent data relative
to the tree One of these will contain the
ply that is currently under analysis and this number will
be stored in the left half of the byte so that what is actually stored
will be the second data counter byte for the start of the ply block in
question. We will assume that this is register 8q
Each time the ply is changed the program will update the first 4 bits of
the second data counter byte and each section of the code that deals with
some particular item of tree data will begin by replacing the last 4 bits
of the second data counter with an appropiate value. For example, the
SELECT code, which operates on the Move byte only, will set these last 4
bits to C.
*CTAB EMPTY and LEGAL codes
*Counts bits in byte contained in scrarchpad 1 and returns results in scratchpad 2
*Named for an old 7094 command that did just this
CAQ
POP
* Scratchpad
* Register Contents
* 0 Current byte of ACTIVE
* 1 Current byte of Passive
* 2 Working space,
* 3
* 4 Count of moves found (on going forward only)
* 5 Counter, defining ACTIVE byte under consideration
* 6 MOVE byte
* 7 FLAG byte
* 8 PLY in the left 4 bits
*This code now occupies about 230 bytes instead of the 200 allowed
*and it will still have to be augmented to handle both Black and White as active.
*EMPTY will probably just preceed FIND
*To generate EMPTY and save it in scratchpad registers O'21', O'22', O'23, O'24'
*Registers O'20' and O'25' are set to zero as guard bytes for off-board references
*Assume that H has been updated, that ACTIVE, PASSIVE and KINGS have been stored,
*On going forward Scratchpad registers 5, 6, and 7 are all set to zero
*On backing up, 6 and 7 are set from RAM
EMPTY LISU 2 This buffer used for EMPTY
LISL 0
LR DC,H H always contains DC value for start of PLY block
CLR
LRI I,A A guard byte at start
BR EMP3
EMP2 LIS 1
ADC
EMP3 LR Q,DC
LM Get ACTIVE byte
LR 0,A Save it temporarily
LIS 4 Index to PASSIVE byte
ADC
LM Get PASSIVE byte
AS 0 Add ACTIVE byte
COM
LR I,A Save it in scratchpad O'20' and increment ISAR
LR DC,Q Reload DC for last used ACTIVE
NI 7
CI 5
BNZ EMP2 Loop
CLR
LRI S,A A guard byte at the end
*To find all moves on going forward along the tree
*The first found move byte will be left in the MOVE byte and the FLAG byte will
*be set to show whether the move is a jump or not and to tell which of the
*possible move bytes is actually saved in the RAM MOVE byte.
*The count of the total number of moves will be left in scratchpad 4.
*This number (to max of 7) will also be stored in the spare bits of the FLAG byte.
*Entry on going forward at FIND, on backing up at Next
NEXT LISU 2
LR DC,H
LI H'C'
FIND LISU 2 EMPTY bytes are here
LISL 1 Remember 0 is a guard byte
LIS 4 Start with Jump moves
BR FIN2
FIN1 CLR
LISL 1 Remember 0 is a guard byte
FIN2 LR 5,A Used to indicate J or N
LIS 3
LR 4,A Used to count starting byte
FIN3 LIS 3
LR 3,A Used to count direction
LR DC,H Start with the first byte of ACTIVE
AS 4 Add to get current byte
ADC
LM Get ACTIVE byte
LR 0,A Save it
AS I Just to increment ISAR for next EMPTY byte
FIN4 LR A,3 Get direction number
AS 5 Add in J or N indicator
DCI FINT
ADC
LM
DCI RFJ
ADC
LR Q,DC
LR PO,Q
FINT DC (RBN-RFJ)
DC (LBN-RFJ)
DC (LFN-RFJ)
DC (RFN-RFJ)
DC (RBJ-RFJ)
DC (LBJ-RFJ)
DC (LFJ-RFJ)
DC (RFJ-RFJ)
RFJ LR A,I Increment to next byte
LR A,D Get EMPTY byte and set ISAR back
SR 1 Shift it right by 1
NI H'77' Save only 6 particular bits
LR 2,A Corrected destination byte
LR DC,H
AS 4
AI 5 INDEX to PASSIVE byte
ADC
LM Get PASSIVE byte
SL 4
LR 1,A
LIS 1
ADC
LM
SR 4
SR 1
BR FINR
LFJ LR A.I Increment to the next byte
LR A,D Get EMPTY byte and set ISAR back
SL 1 Shift it left by 1
NI H'EE' Save only specific 6 bits
LR 2,A
LR DC,H
AS 4
AI 5 INDEX to PASSIVE byte
ADC
LM Get PASSIVE byte
SL 1 Shift it left by 5 total
SL 4 Shift it left by 4
LR 1,A Save it
LIS 1 Now the next PASSIVE byte
ADC
LM
SR 4
BR FINR
LBJ
LR DC,H
AS 4
AI 8 INDEX to PASSIVE byte
ADC
LM Get King byte
NS A,0 AND it to Active from 0
BZ FINR No backward moves for this byte
LR 0,A And save it
LR A,D Decrement to earlier byte
LR A,I Get EMPTY byte AND SHIFT ISAR BACK
SL 1 Shift it left by 1
NI H'EE' Save only 6 particular bits
LR 2,A
LI H'F8' Actually -4
ADC to index to passive byte
LM Get PASSIVE byte
SR 4
LR 1,A
LIS 1 Now the next PASSIVE byte
ADC
LM
SL 4 Shift it left by 5
SL 1 Shift it left by 5
BR FINR
RBJ LR DC,H
AS 4
AI 8 INDEX to PASSIVE byte
ADC
ADC
LM Get King byte
NS A,0
BZ FINR No backward moves for this byte
LR 0,A
LR A,D Decrement ISAR
LR A,I Get EMPTY byte and reset ISAR
SL 1 Shift it left by 1
NI H'EE' Save only specific 6 bits
LR 2,A
LI H'FD' Actually -3
ADC
LM Get PASSIVE byte
SL 4 Shift it left by 5
SL 1 Shift it left by 5
LR 1,A Save it
LIS 1 Now the next PASSIVE byte
ADC
LM
SR 4
BR FINR
RFN LR A,I Get empty byte
SL 4
LR 1,A
LR A,D
SR 4
SR 1
BR FINR
LFN LR A,I
SL 4
SL 1
LR 1,A
LR A,D
SR 4
BR FINR
LBN LR DC,H
AS 4
AI 8 INDEX to PASSIVE byte
ADC
LM Get King byte
NS A,0 AND it to Active from 0
BZ FINR No backward moves for this byte
LR 0,A And save it
LR A,D
SR 4
LR 1,A
LR A,I
SL 4
SL 1
BR FINR
RBN LR DC,H
AS 4
AI 8 INDEX to PASSIVE byte
ADC
LM Get King byte
NS A,0 AND it to Active from 0
BZ FINR No backward moves for this byte
LR 0,A And save it
LR A,D
SR 4
SR 1
LR 1,A
LR A,I
SL 4
FINR AS 1 Add in other PASSIVE pieces
NS 0 And in the ACTIVE byte
NS 2 And the modified PASSIVE byte
BZ FINL Branch on zero
LR 1,A Save temporarily
PI CTAB To count bits on in 1 and leave results in 2
LR A,6 Count of moves found
AS 2
LR 6,A
LR DC,H Reset to locate MOVE byte
LIS H'C'
ADC
LM
NI H'FF' To set status
BNZ FINL A move byte is already stored
LR A,1 Get move byte
ST and store it
LIS 1 Now go to flag byte
ADC
LR A,3 Get 2 bits that define direction
AS 5 Add J or N bit
SL 1
SL 1
AS 4 Add 2 bits defining the ACTIVE byte
ST Store the new FLAG byte
FINL DS 3 Decrement direction
BP FIN4 BR if not negative
DS 4 Decrement byte count
BP FIN3
LR A,5
DS 5 Decrement J or N indicator
BP FIN1
*Now to add count of moves found to Flag byte
LR DC,H
LIS H'D' Get back to the flag bit
ADC
LR A,6
CI 7
BN FIN6
LIS 7 Limit count to 7
BR FIN7
FIN6 LR A,6
FIN7 SL 5
LR 6,A Put limited value back in 6
AM Add in old flag byte
ST and store
Subroutine to move 4 bytes from RAM to Scratchpad registers 16 thru 19
RASC LISL 0
BR RASE
*Subroutine to move 4 bytes from RAM to SC 20 thru 23
RAS2 LISL 4
RASE LISU 2
LIS 4
LR 0,A
RASL LM
LR A,I
DS 0
BNZ RASL
POP
*Subroutine to move 4 bytes from SC24 thru 28 to RAM (Kings)
SCR3 LISL 0
LISU 3
BR SCRF
*Subroutine for moving 4 bytes from Scratchpad registers 16 thru 19 to RAM
SCR1 LISL 0
BR SCRE
*Subroutine to move 4 bytes from SC 20 thru 23 to RAM (former passive)
SCR2 LISL 4
SCRE LISU 2
SCRF LIS 4
LR 0,A
SCRL LR A,I
ST
DS 0
BNZ SCRL
POP
*To move pieces forward with sides reversed
FORW LR DC,H
LI H'10'
ADC
LR Q,DC We will need this later
LIS 4
LR 0,A To use as a counter
ADC
XDC
LR DC,H
PI FOR2 Former ACTIVE to PASSIVE
XDC
LR DC,Q
XDC
PI FOR2 FORMER PASSIVE to ACTIVE
LR DC,Q
LIS 8
ADC
XDC
PI FOR2 KINGS to KINGS
XDC
CLR
ST Zero MOVE byte
ST and FLAG
ST and SCOREs
ST and SCOREs
POP
* Registers, Subroutines
Tree data will be stored in blocks of 16 bytes, one for each ply depth. Data
within each block will be located as follows:
Bytes Contents
0 thru 3 ACTIVE pieces
4 thru 7 PASSIVE pieces
8 thru 11 KINGS
12 MOVE byte
13 FLAG byte (dir in 0,1 byte in 2,3 J in 4 H'FF' going fore)
14 SCORE
15 unassigned
When blocks of data are to be operated on, they are moved from RAM into the
Scratchpad registers 16 thru 31. Scratchpad registers 32 to 35 are used for
EMPTY as created by code EMPTY with 36 left empty as a guard. At the time
that Empty is filled register 31 is also set to zero as a lower guard.
Scratchpad registers 0 thru 8 are normally used as follows:
Register Usage
0 general purpose
1
2 King move flag
3 Move byte during generation
4 Byte pointer (bits 0 and 1 from FLAG byte)
5 Move direction (bits 2, 3 and 4 from FLAG byte)
6 MOVE bit extracted from MOVE
7 FLAG byte for analysis
8 Color of ACTIVE (0 if Black)
*Subroutine to move 4 bytes from one location in RAM to another
FOR2 LIS 4
LR 0,A
FORL LM Get Byte to move
XDC
ST Store in new location
XDC
DS 0
BNZ FORL Loop
POP
*Subroutine to move 16 bytes from RAM into SC 16 thru 31
RASC LISU 2
LISL 0
LIS 8
LR 0,A
PI RASM
LISU 3
LISL 0
LI 8
LR 0,A
PI RASM
RASM LIS 4
LR 0,A
RASL LM
LR S,A
DS 0
BNZ RASL
POP
*Subroutine to move 16 bytes from SC 16 thru 31 to RAM, reversing ACTIVE and PASSIVE
SCRC LISU 2
LISL 4
PI SCRM
LISL 0
PI SCRM
LISU 3
LISL 0
PI SCRM
PI SCRM
POP
SCRM LIS 4
LR 0,A
SCRL LR A,I
ST
DS 0
BNZ SCRL
POP
*To compute 4 bytes which show the empty squares on the board.
*These are stored in SC 33 thru 36 with SC 32 and SC 37 set to zero as guards.
*Note especially that the EMPTY locations are displaced
EMPTY LISU 3
LISL 0
CLR
LR S,A Make sure guard byte is empty
LISU 1 Start with ACTIVE
LIS 4
LR 0,A
BR EMP3
EMP2 LR A,SI
AI H'2F' Actually subtracting 17
LR SI,A
EMP3 LR A,S
LR 1,A
LR A,IS
AI 4
LR SI,A
LR A,S
AS 1
LR 1,A
LR A,SI
AI H'D' Add 13 to get to the correct EMPTY location
LR IS,A
LR A,1
COM
LR I,A
DS 0
BNZ EMP2
CLR
LR S,A Upper guard byte
POP
* FORE AFT FIND
** TEST FOR MAX DEPTH MUST BE PUT IN THE FOLLOWING
FORE LR DC,H
LI H'10'
ADC
LR H,DC
PI RASC Get correct board into SC
LI H'FF'
LR 6,A So all moves will be found
PI FIND
**Score back-up must be put into the following****
and test made for ply for time to stop
AFT LR A,11
COM
AI H'10'
COM
LR DC,H
PI RASC
LISU 2
LISL 5
LR A,I
LR 6,A The remaining MOVE byte
LR A,S
NI H'FF' To set STATUS
LR A,S
LR 7,A The FLAG byte
BNZ SELE
NI H'F' Remove J bit
AI 1
LR 4,A
NI H'10' Is board exhausted
BZ AFT Must back up more
LR A,4
NI 3
LR 5,A The direction in 5
LR A,4
SR 1
SR 1
LR 4,A The byte pointer in 4
**MUST USE A JUMP TABLE WITH 5 TO ENTER FIND PROPERLY
FIND LISU 2
LISL 0 Start with byte 0
*Look for jump moves first
LIS 0
LR 4,A Used to distinguish byte
JLOP LR A,S
LR 6,A We will need this several times
LR 3,A So save it in 2 places
RFJ LR A,IS
LR 4,A We'll have to get back here
LR A,8 Get color of Active
NI H'7' To set status
BZ RFJ2 Black is ACTIVE
LISU 2 Only kings can move this way
LR A.S
NS 6
BZ RBJ No RF or LF moves for this byte
LR 3,A Correct for kings
RFJ2 LR A,IS
AI 2 To next forward EMPTY byte (remember displacement)
LR IS,A
LISU 3
LR A,S
SR 1
NI H'77' Save 6 particular bits only
NS 3
LR 3,A
LR A,IS
AI 2 (remember displacement)
LR IS,A
LISU 2 This gets us to the right KING byte
PI RFJN This returns the RFJ byte in 3
BZ LFJ
LIS H'C' For the MOVE byte location
LR IS,A
LR A,S Has one been stored?
NI H'FF' To set STATUS
BNZ FIN3
LR A,3
LR I,A Store MOVE and index to FLAG
LR A,4 For the FLAG byte
SL 1
SL 1
AI H'11' RFJ pointer
LR S,A
FIN3 LR A,6 This is H'FF' if going forward and 0 on back-up
XI H'FF'
BZ FIN4
BR SELE Stop after finding a valid MOVE byte
FIN4 PI CAQ To count bits in 3
LFJ
LR A,4 Get back in step
LR IS,A
LR A,S
LR 3,A
*THIS CODE WILL BE QUITE SIMILAR TO RLJ CODE
*Subroutine used both by RFJ and RJN
RFJN LR A,S
SL 4
LR 0,A
LR A,IS
AI 1
LR IS,A
LR A,S
SR 4
SR 1
AS 0
NS 3
LR 3,A The RFJ or RJ byte
POP
LFJN LR A,S
SL 4
SL 1
LR 0,A
LR A,IS
AI 1
LR IS,A
LR A,S
SR 4
AS 0
POP
*SELECT is entered with H set for the correct ply position in RAM
*SELECT extracts one bit (the rightmost one) from the MOVE byte storing it in
Scratchpad 6 and it puts the FLAG byte in SC 7 with the last 2 bits into SC 5.
SELECT LR DC,H Load DC with starting location for current ply
LI H'C' The relative location of the MOVE byte
ADC Add it to the DC
LR Q,DC Save it as DC will be incremented willy-nilly
LM Get the byte to be operated on
LR 0,A Save it temporarily
NI H'FF' TO set status byte
BZ GETB Branch on zero to code to get next MOVE byte
COM Complement the ACC
AI 1 Really subtracting 1
NS 0 Extract right-most on-bit only
LR 6,A Save it in 6
XS 0 This gets the remaining bits
LR DC,Q (DC was incremented, remember)
SM So put them back
LM Get FLAG byte while we are at it
LR 7,A Save it in 7
NI 3 Separate the byte indicator part
LR 5,A Save it in 5
LR A,7
SR 1
SR 1 Separate out the direction bits
LR 4,A Save them in 4
*Now process ACTIVE and KINGS for source deletion
DELE LR DC,H
LISU 2
LISL 0
LR A,IS
AS 5
LR IS,A Locate ACTIVE byte with piece moving
LR A,S
XS 6 Delete moving piece
LR S,A from byte
LISU 3 To get to corresponding KING byte
LR A,S
NS 6 Was the piece a king?
BZ DEL2
XS S If it was delete king bit
LR S,A
LI 7 Non-zero in 2 for king
DEL2 LR 2,A Save as a flag for kind of piece moving
*Now locate captured piece if jump or find destination in normal move
LR 6 Recall MOVE byte
SR 4
BZ INRH Bit was in right half of byte
INLH LR 3,A Save partially shifted MOVE bit
LR A,4 Get direction
NI 1 To test right-most bit
BZ INL2 RF or LB move where 4 shift is correct
LR A,3
SR 1 LF and LB require an additional shift
LR 3,A
INL2 LR A,4 Now test for fore or aft
NI 2
BZ BOTH Bit was off so forward move and no byte shift needed
LR A,D Only to decrement ISAR
INL3 BR BOTH
INRH LR 6 Get MOVE byte back
SL 4 Left shift if in right half
LR 3,A Save partially shifted MOVE bit
LR A,4 Get direction
NI 1
BNZ INR2 LF or RB wwhere 4 shift is correct
LR A,3
SL 1 RF and RB require an additional shift
LR 3,A
INR2 LR A,4 Now test fore and aft
NI 2
BNZ BOTH
LR A,I Only to increment ISAR
BOTH LR A,4 Now is this a jump or a normal move?
NI 4
BZ NORM Normal move case
LR A,S Get King Byte corresponding to captured piece
NS 3 Was piece a king?
BZ BOT2 No
XS 3 Delete it
LR S,A And replace byte
BOT2 LISU 2 Get back to right buffer for ACTIVE and PASSIVE
LR A,IS
AI 4 Increment to PASSIVE byte
LR IS,A
LR A,S Get appropiate PASSIVE byte
XS 3 Delete capture
LR S,A And return byte
LISU 2 Back to moved from location
LISL 0
LR A,IS
AS 5
LR IS,A
LR A,4 Get direction
NI 1 Test for right or left
BZ BOT3
LR A,6
SR 1
BZ BOT4
BOT3 LR A,6
SL 1
BOT4 LR 3,A Save displaced bit in 3
LR A,4
NI 2 Test for fore or aft
BZ BOT5
LR A,D Decrement ISAR
BZ BOT6
BOT5 LR A,I Increment ISAR
BOT6 LR A,S Now get right byte
AS 3 Insert piece
LR S,A
LR A,2 Get king indicator
NI 7
BZ BOT7 Not a king
LR A,IS
AI 4 Go to correct king byte
LR A,S
AS 3
LR S,A
*Now restore pieces to RAM, switching ACTIVE and PASSIVE
BOT7 PI SCRA
*Now make a normal move, (remember we were indexed to the king buffer)
NORM LR A,2 This was set to non-zero if King moving
NI 7
BZ NOR2 Not a king
LR A,S Get corresponding king byte for destination
AS 3 Insert moved king
LR S,A And replace byte
NOR2 LISU 2 Get back to Active pieces
LR A,S
AS 3
LR S,A Put in moved piece
*Normal move completed
UPDATE
Having selected a piece to be moved the program notes the appropiate byte
and direction from the FLAG word and then proceeds to generate the
resulting board. The final destination of the moving piece relative to its
initial location can be easily determined by a table look-up operation
but this may take more space than is justified. On the other hand there are
numerous factors that must be considered if this is to be computed and it is
not at all certain as to which procedure will take less space. Both methods
will probably have to be coded before a decision can be reached.
Evaluation
The amount of code space required for the evaluation is perhaps subject to
the greatest compression or expansion of any part of the program. The
writing of this part of the code can well be left until after some of the
other parts have been stabilized.
α-β Scoring
The Alpha Beta algorithm is the most important algorithm that is involved in
a tree search. It is also the hardest to explain although every one who plays
games such as checkers knows it instinctively and makes full use of it in
his own play. This is not the place to elaborate on this subject but a great
deal of care must be given to the proper programming of this part of the code.
My present guess that it can be done in 50 bytes but I could be grossly in
error on this. The methods that I have used for this previously have been
rather wasteful of code space.
Opponents move checking
This can most easily be done by using the LEGAL move generator to find out
all of the available moves and then to simply see if the opponents move is in
this list. 30 extra instructions should suffice for this.
The problem of providing the mechanism for the opponent to enter his move is
perhaps harder to solve and I will need some help on this.
DISPLAY
I am not at present well enough informed about the display features associated
with the equipment to comment on this. I have assumed that at least 200 bytes
would have to be allowed for this function.